package com.wk.code.wkserver.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wk.code.wkserver.constant.Constant;
import com.wk.code.wkserver.constant.NumberConstant;
import com.wk.code.wkserver.constant.enums.TechOrderStatusEnum;
import com.wk.code.wkserver.constant.enums.UserOrderStatusEnum;
import com.wk.code.wkserver.constant.enums.UserTypeEnum;
import com.wk.code.wkserver.controller.app.WalletController;
import com.wk.code.wkserver.entity.*;
import com.wk.code.wkserver.mapper.DemandOrderMapper;
import com.wk.code.wkserver.request.app.DemandOrderRequest;
import com.wk.code.wkserver.response.app.DemandOrderResponse;
import com.wk.code.wkserver.service.*;
import com.wk.code.wkserver.utils.DateUtils;
import com.wk.code.wkserver.utils.MoneyUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wq
 * @since 2021-08-15
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class DemandOrderServiceImpl extends ServiceImpl<DemandOrderMapper, DemandOrder> implements IDemandOrderService {

    @Resource
    private IUserService userService;

    @Resource
    private IDemandService demandService;

    @Resource
    private IOrderTakingRecordService orderTakingRecordService;

    @Resource
    private IEstimateAmountService estimateAmountService;

    @Resource
    private ISysConfigService sysConfigService;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void createDemandOrder(BigDecimal orderAmount, BigDecimal techAmount, Integer demandId, Integer userId, Integer techUserId) {
        DemandOrder demandOrder = new DemandOrder();
        demandOrder.setDemandId(demandId);
        demandOrder.setOrderNo(DateUtils.dateTimeNow());
        demandOrder.setOrderAmount(orderAmount);
        SysConfig sysConfig = sysConfigService.selectByFieldValue(Constant.SETTLED_RATIO);
        if (Objects.nonNull(sysConfig)) {
            demandOrder.setTechAmount(orderAmount.multiply(new BigDecimal(sysConfig.getFieldValue())));
        }
        //设置技术用户订单状态
        demandOrder.setTechOrderStatus(TechOrderStatusEnum.PROCESSING.getCode());
        demandOrder.setUserOrderStatus(UserOrderStatusEnum.PLACED_ORDERS.getCode());
        demandOrder.setUserId(userId);
        demandOrder.setTechUserId(techUserId);
        save(demandOrder);
        log.info("创建下单订单成功:" + JSONObject.toJSONString(demandOrder));
    }

    @Override
    public List<DemandOrderResponse> demandOrderList(Integer userId, DemandOrderRequest request) {
        User user = userService.selectById(userId);
        if (Objects.nonNull(user)) {
            return buildDemandUserOrder(userId, request);
        }
        return null;
    }

    /**
     * 技术用户订单
     *
     * @param userId  用户ID
     * @param request 请求参数
     * @return List<DemandOrderResponse>
     */
    private List<DemandOrderResponse> buildTechUserOrder(Integer userId, DemandOrderRequest request) {

        //技术也有可能发单
        if (request.getType().equals(NumberConstant.ONE)) {
            //待用户待下单
            List<OrderTakingRecord> list = orderTakingRecordService.selectOrderTakingRecords(Collections.singletonList(userId));
            if (!CollectionUtils.isEmpty(list)) {
                ArrayList<Integer> demandNoTakings = new ArrayList<>();
                //查询该需求的订单 如果没有则说明用户未下单
                List<Integer> demandIds = list.stream().map(OrderTakingRecord::getDemandId).collect(Collectors.toList());
                for (Integer demandId : demandIds) {
                    DemandOrder demandOrder = baseMapper.selectOne(new LambdaQueryWrapper<DemandOrder>().eq(DemandOrder::getDemandId, demandId));
                    if (Objects.isNull(demandOrder)) {
                        demandNoTakings.add(demandId);
                    }
                }
                //遍历查询未下单的需求
                List<Demand> demands = demandService.selectDemandList(demandNoTakings);
                if (!CollectionUtils.isEmpty(demands)) {
                    return demands.stream().map(x -> {
                        DemandOrderResponse response = new DemandOrderResponse();
                        if (StringUtils.isNotEmpty(x.getImages())) {
                            response.setImage(JSONObject.parseArray(x.getImages()).getString(0));
                        }
                        response.setTitle(x.getTitle());
                        User user = userService.selectById(x.getUserId());
                        response.setUserAvatar(user.getAvatar());
                        response.setUsername(user.getNickname());
                        LocalDateTime createTime = list.stream().filter(e -> e.getDemandId().equals(x.getId())).findFirst().get().getCreateTime();
                        response.setOrderTime(DateUtils.localDateTime2DateStr(DateUtils.YYYY_MM_DD_HH_MM_SS, createTime));
                        EstimateAmount estimateAmount = estimateAmountService.detail(x.getEstimateAmountId());
                        response.setEstimateAmount(estimateAmount.getPrice());
                        return response;

                    }).collect(Collectors.toList());
                } else {
                    return null;
                }
            }
        }
        LambdaQueryWrapper<DemandOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DemandOrder::getTechUserId, userId);
        if (request.getType().equals(NumberConstant.TWO)) {
            wrapper.eq(DemandOrder::getTechOrderStatus, NumberConstant.ONE);
        }
        if (request.getType().equals(NumberConstant.THREE)) {
            wrapper.eq(DemandOrder::getTechOrderStatus, NumberConstant.ONE);
        }
        if (request.getType().equals(NumberConstant.FOUR)) {
            wrapper.eq(DemandOrder::getTechOrderStatus, NumberConstant.TWO);
        }
        wrapper.orderByDesc(DemandOrder::getCreateTime);
        List<DemandOrder> orderList = baseMapper.selectPage(request.page(), wrapper).getRecords();
        if (!CollectionUtils.isEmpty(orderList)) {
            return orderList.stream().map(x -> {
                DemandOrderResponse response = new DemandOrderResponse();
                response.setOrderNo(x.getOrderNo());
                response.setOrderAmount(MoneyUtils.bigDecimal2Str(x.getOrderAmount()));
                response.setStatus(x.getTechOrderStatus());
                User user = userService.selectById(x.getUserId());
                response.setUserAvatar(user.getAvatar());
                response.setUsername(user.getNickname());
                return getDemandOrderResponse(x, response);
            }).collect(Collectors.toList());
        }
        return null;
    }

    private DemandOrderResponse getDemandOrderResponse(DemandOrder x, DemandOrderResponse response) {
        response.setOrderTime(DateUtils.localDate2Time(x.getCreateTime()));
        Demand demand = demandService.selectOrderDemand(x.getDemandId());
        if (Objects.nonNull(demand)) {
            if (StringUtils.isNotEmpty(demand.getImages())) {
                response.setImage(JSONObject.parseArray(demand.getImages()).getString(0));
            }
            response.setTitle(demand.getTitle());
        }
        return response;
    }

    /**
     * 需求用户订单列表
     *
     * @param userId  用户ID
     * @param request 请求参数
     * @return List<DemandOrderResponse>
     */
    private List<DemandOrderResponse> buildDemandUserOrder(Integer userId, DemandOrderRequest request) {
        LambdaQueryWrapper<DemandOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DemandOrder::getUserId, userId);
        wrapper.orderByDesc(DemandOrder::getCreateTime);
        if (request.getType().equals(NumberConstant.ONE)) {
            //查询该用户的需求
            List<Demand> userDemands = demandService.list(new LambdaQueryWrapper<Demand>().eq(Demand::getUserId, userId).
                    isNotNull(Demand::getTechUserId));
            if (!CollectionUtils.isEmpty(userDemands)) {
                List<Integer> techUserIds = userDemands.stream().map(Demand::getTechUserId).collect(Collectors.toList());
                //待用户待下单
                List<OrderTakingRecord> list = orderTakingRecordService.selectOrderTakingRecords(techUserIds);
                if (!CollectionUtils.isEmpty(list)) {
                    ArrayList<Integer> demandNoTakings = new ArrayList<>();
                    //查询该需求的订单 如果没有则说明用户未下单
                    List<Integer> demandIds = list.stream().map(OrderTakingRecord::getDemandId).collect(Collectors.toList());
                    for (Integer demandId : demandIds) {
                        DemandOrder demandOrder = baseMapper.selectOne(new LambdaQueryWrapper<DemandOrder>().
                                eq(DemandOrder::getDemandId, demandId));
                        if (Objects.isNull(demandOrder)) {
                            demandNoTakings.add(demandId);
                        }
                    }
                    //遍历查询未下单的需求
                    List<Demand> demands = demandService.selectDemandList(demandNoTakings);
                    if (!CollectionUtils.isEmpty(demands)) {
                        return demands.stream().map(x -> {
                            DemandOrderResponse response = new DemandOrderResponse();
                            if (StringUtils.isNotEmpty(x.getImages())) {
                                response.setImage(JSONObject.parseArray(x.getImages()).getString(0));
                            }
                            response.setTitle(x.getTitle());
                            User user = userService.selectById(x.getTechUserId());
                            response.setTechUserAvatar(user.getAvatar());
                            response.setTechUsername(user.getNickname());
                            LocalDateTime createTime = list.stream().filter(e -> e.getDemandId().equals(x.getId())).
                                    findFirst().get().getCreateTime();
                            response.setOrderTime(DateUtils.localDateTime2DateStr(DateUtils.YYYY_MM_DD_HH_MM_SS, createTime));
                            EstimateAmount estimateAmount = estimateAmountService.detail(x.getEstimateAmountId());
                            response.setEstimateAmount(estimateAmount.getPrice());
                            return response;

                        }).collect(Collectors.toList());
                    } else {
                        return null;
                    }
                }
            }

        }
        if (request.getType().equals(NumberConstant.TWO)) {
            wrapper.eq(DemandOrder::getUserOrderStatus, NumberConstant.ONE);
        }
        if (request.getType().equals(NumberConstant.THREE)) {
            wrapper.eq(DemandOrder::getUserOrderStatus, NumberConstant.ZERO);
        }
        if (request.getType().equals(NumberConstant.FOUR)) {
            wrapper.eq(DemandOrder::getUserOrderStatus, NumberConstant.TWO);
        }
        List<DemandOrder> orderList = baseMapper.selectPage(request.page(), wrapper).getRecords();
        if (!CollectionUtils.isEmpty(orderList)) {
            return orderList.stream().map(x -> {
                DemandOrderResponse response = new DemandOrderResponse();
                response.setOrderNo(x.getOrderNo());
                User user = userService.selectById(x.getTechUserId());
                response.setTechUserAvatar(user.getAvatar());
                response.setTechUsername(user.getNickname());
                response.setOrderAmount(MoneyUtils.bigDecimal2Str(x.getOrderAmount()));
                response.setStatus(x.getUserOrderStatus());
                return getDemandOrderResponse(x, response);
            }).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public DemandOrder selectByDemandId(Integer demandId) {
        return baseMapper.selectOne(new LambdaQueryWrapper<DemandOrder>().
                eq(DemandOrder::getDemandId, demandId));
    }

    @Override
    public BigDecimal selectEstimateAccount(Integer userId) {
        User user = userService.selectById(userId);
        if (!user.getRegisterType().equals(UserTypeEnum.DEMAND_USER.getCode())) {
            //只有技术才有预计入账
            List<DemandOrder> demandOrders = baseMapper.selectList(new LambdaQueryWrapper<DemandOrder>().eq(DemandOrder::getTechUserId, userId).
                    eq(DemandOrder::getTechOrderStatus, TechOrderStatusEnum.PROCESSING.getCode()));
            if (!CollectionUtils.isEmpty(demandOrders)) {
                Optional<BigDecimal> optional = demandOrders.stream().map(DemandOrder::getTechAmount).reduce(BigDecimal::add);
                if (optional.isPresent()) {
                    return optional.get();
                }
            }
        }
        return new BigDecimal("0.00");

    }

    @Override
    public List<DemandOrderResponse> mineTakingOrder(Integer userId, DemandOrderRequest request) {
        User user = userService.selectById(userId);
        if (Objects.nonNull(user)) {
            return buildTechUserOrder(userId, request);
        }
        return null;
    }

    @Override
    public void deleteByDemandId(Integer demandId) {
        baseMapper.delete(new LambdaQueryWrapper<DemandOrder>().eq(DemandOrder::getDemandId, demandId));
    }

}
